package org.lansir.af.view;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.lansir.af.R;
import org.lansir.af.database.Database;
import org.lansir.af.dataview.DataViewActivity;
import org.lansir.af.dataview.DataViewItem;
import org.lansir.af.dataview.DataViewItemActivity;
import org.lansir.af.model.CalendarFactory;
import org.lansir.af.model.CalendarKey;
import org.lansir.af.model.DayModel;
import org.lansir.af.ui.CommonFragment;

import android.content.Context;
import android.graphics.Canvas;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

public class CalendarView extends LinearLayout {
	private static final String TAG = "CalendarView";
	
	private static final int TIME_FLAGS = DateUtils.FORMAT_SHOW_DATE
	| DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_WEEKDAY;

	private String[] _dateOfWeekHedder = null;
	private TextView _monthTitle = null;

	private float _monthTitleSize = 18f;
	private DayModel _currentDay = CalendarFactory.getToday();
	private TableLayout _calendarTable = null;
	private AbstractCalendarCellView[][] _cells = new AbstractCalendarCellView[6][7];
	private Class<?> _clazz = null;
	private CalendarCellEventListener _onCalendarCellSelectedListener = null;
	private CalendarCellViewParam _calendarCellViewParam = null;
	private CalendarViewFlipperHolder _viewFlipper = null;
	private LayoutInflater _inflater;
	private Database _userdb;
	private DataViewActivity _dataViewActivity;
	CalendarView(Context context, Class<?> clazz, String[] dateOfWeekHedder,  CalendarCellViewParam calendarCellViewParam, Database userdb) {
		super(context);
		_clazz = clazz;
		_dateOfWeekHedder = dateOfWeekHedder;

		_calendarCellViewParam = calendarCellViewParam;
		_userdb = userdb;
		_dataViewActivity = new DataViewActivity(_userdb);
		_dataViewActivity.reloadTable();
		_inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
		setWillNotDraw(false);
		setOrientation(LinearLayout.VERTICAL);
		this.setPadding(2, 0, 0, 2);
	}

	void setCalendarViewFlipperHolder(CalendarViewFlipperHolder viewFlipper){
		_viewFlipper = viewFlipper;
	}

	void addMonthTitle() {
		View vMonthTitle = _inflater.inflate(R.layout.fragment_month_title, null);
		ImageView leftIndicator = (ImageView) vMonthTitle.findViewById(R.id.indicator_left);
		ImageView rightIndicator = (ImageView) vMonthTitle.findViewById(R.id.indicator_right);
		leftIndicator.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v) {
				onLastMonth();
			}			
		});
		rightIndicator.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v) {
				onNextMonth();
			}			
		});
		_monthTitle = (TextView) vMonthTitle.findViewById(R.id.month_title);
		_monthTitle.setGravity(Gravity.CENTER);
		_monthTitle.setTextSize(_monthTitleSize);
		addView(vMonthTitle);
	}

	void addCalendarTable() {
		_calendarTable = new TableLayout(getContext());
		_calendarTable.setStretchAllColumns(true);

		TableRow header = new TableRow(getContext());

		for(String str : _dateOfWeekHedder){
			TextView text = new TextView(getContext());
			text.setText(str);
			text.setGravity(Gravity.CENTER);
			text.setTextSize(15);
			header.addView(text);
			text.setBackgroundResource(R.drawable.calendar_grid_week);
		}
		_calendarTable.addView(header);
		Class<?>[] types = { Context.class, CalendarView.class, CalendarCellViewParam.class};
		Object[] args = { getContext(), this, _calendarCellViewParam};
		Constructor<?> constructor;
		try {
			constructor = _clazz.getConstructor(types);
			for (int i = 0; i < _cells.length; i++) {
				TableRow tableRow = new TableRow(getContext());

				for (int j = 0; j < _cells[0].length; j++) {
					_cells[i][j] = (AbstractCalendarCellView) constructor
							.newInstance(args);
					
					tableRow.addView(_cells[i][j]);
				}
				_calendarTable.addView(tableRow);
			}
			addView(_calendarTable);
		} catch (SecurityException e) {
			throw new RuntimeException(e);
		} catch (NoSuchMethodException e) {
			throw new RuntimeException(e);
		} catch (IllegalArgumentException e) {
			throw new RuntimeException(e);
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (InvocationTargetException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
	}

	public void onNextMonth() {
		_viewFlipper.onNextMonth(this);
	}

	public void onLastMonth() {
		_viewFlipper.onLastMonth(this);
	}

	public DayModel getCurrentDay(){
		return _currentDay;
	}

	public void setCurrentDay(DayModel day){
		_currentDay = day;
		repaintCalendar();
	}

	public void toNextMonth() {
		Log.i("month", "toNextMonth");

		_currentDay = CalendarFactory.getNextMonthDayModel(_currentDay);
		repaintCalendar();
	}

	public void toLastMonth() {
		Log.i("month", "toLastMonth");

		_currentDay = CalendarFactory.getLastMonthDayModel(_currentDay);
		repaintCalendar();
	}

	public void setOnCalendarCellSelectedListener(CalendarCellEventListener onCalendarCellSelectedListener){
		_onCalendarCellSelectedListener = onCalendarCellSelectedListener;
	}
	
	public void refreshCalendar(){
		_dataViewActivity.reloadTable();
		CalendarFactory._calendarDayCache.clear();
		repaintCalendar();
	}

	public void repaintCalendar() {
		_monthTitle.setText(DateUtils.formatDateTime(getContext(), _currentDay.toCalendar().getTimeInMillis(), TIME_FLAGS));
		DayModel targetDay = CalendarFactory.getCalendarStartSunDay(_currentDay);
		//_monthTitle.setText(_monthTitleSDF.format(_currentDay.getTime()));
		CalendarFactory.setShownMonth(_currentDay.getParentMonthModel());
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DAY_OF_MONTH, 1);
		_dataViewActivity.filterData(cal, CommonFragment.ViewType.MONTH);
		List<DataViewItem> dataViewItems = _dataViewActivity.getRowsForView();

		for(DataViewItem item : dataViewItems){
			DataViewItemActivity dvai = (DataViewItemActivity) item;
			
			if(!dvai.isRepeat()){
				CalendarKey calKey = new CalendarKey(dvai.getStartDate());
				CalendarFactory._calendarDayCache.add(calKey);
				Log.v(TAG, "year:" + calKey.getYear() + ",month:" + calKey.getMonth() + ",day:" + calKey.getDay());
			}else{
				Calendar repeatCal = targetDay.toCalendar();
				
//				Log.v(TAG, "startDate:" + calKey.getYear() + ",Month:" + calKey.getMonth() + ",Day:" + calKey.getDay());
				int iDay = 0;
			    for (int iWeek = 0; iWeek < _cells.length; iWeek++)
			    {  			
			    	for (int iWeekDay = 0; iWeekDay < _cells[0].length; iWeekDay++)
			    	{
			    		
			    		if (dvai.getVisibleDay(iDay)){
			    			CalendarKey calkey = new CalendarKey(repeatCal);
			    			if(!CalendarFactory._calendarDayCache.contains(calkey))
			    				CalendarFactory._calendarDayCache.add(calkey);

			    		}
			    		repeatCal.add(Calendar.DAY_OF_YEAR, 1);
			    			//item.setDayData(iWeekDay, true);
			    		iDay++;
			    		
			    	}		    	
			    }	
//				Log.v(TAG, "getVisibleDays:" + dvai.getVisibleDay(iDay));
			}
			
			
		}
		
		for (AbstractCalendarCellView[] cellRow : _cells) {
			for (AbstractCalendarCellView cell : cellRow) {
				CalendarKey calKey = new CalendarKey(targetDay.toCalendar());
				Log.v(TAG, "key:" + calKey.hashCode());
				if(CalendarFactory._calendarDayCache.contains(calKey)){
					targetDay.setMark(true);
//					Log.v(TAG, "targetDay mark");
				}
				cell.setDayModel(targetDay);
				if(_onCalendarCellSelectedListener != null){
					cell.setCalendarCellEventListener(_onCalendarCellSelectedListener);
				}
				targetDay = CalendarFactory.getNextDay(targetDay);
			}
		}
	}
}
